﻿using Microsoft.EntityFrameworkCore;
using Singer.Shared.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Singer.Middleware.EFCore
{
    public interface IBaseRepository<TDbContext, TEntity>
        where TDbContext : EFCoreDbContext
        where TEntity : class, IEntity
    {
        //DDD中，所有数据库操作都应在仓储层。这里DbContext 和 Table 不应公开。（这里方便测试用。实际业务中不应公开）
        TDbContext DbContext { get; }
        DbSet<TEntity> Table { get; }

        void Attach(TEntity entity);
        void Attach(IEnumerable<TEntity> entities);

        void RemoveAttach(TEntity entity);
        void RemoveAttach(IEnumerable<TEntity> entities);

        int SaveChanges();
        Task<int> SaveChangesAsync();

        int Add(TEntity entity, bool saveChanges = true);
        Task<int> AddAsync(TEntity entity, bool saveChanges = true);
        int Add(IEnumerable<TEntity> entities, bool saveChanges = true);
        Task<int> AddAsync(IEnumerable<TEntity> entities, bool saveChanges = true);

        int Update(TEntity entity, bool saveChanges = true);
        Task<int> UpdateAsync(TEntity entity, bool saveChanges = true);
        int Update(IEnumerable<TEntity> entities, bool saveChanges = true);
        Task<int> UpdateAsync(IEnumerable<TEntity> entities, bool saveChanges = true);

        int Delete(TEntity entity, bool saveChanges = true);
        Task<int> DeleteAsync(TEntity entity, bool saveChanges = true);
        int Delete(IEnumerable<TEntity> entities, bool saveChanges = true);
        Task<int> DeleteAsync(IEnumerable<TEntity> entities, bool saveChanges = true);
        int Delete(Expression<Func<TEntity, bool>> expWhere);
        Task<int> DeleteAsync(Expression<Func<TEntity, bool>> expWhere);

        TEntity? Get(Expression<Func<TEntity, bool>>? expWhere = null, bool noTracking = false);
        Task<TEntity?> GetAsync(Expression<Func<TEntity, bool>>? expWhere = null, bool noTracking = false);


        int Count(Expression<Func<TEntity, bool>>? expWhere = null);
        Task<int> CountAsync(Expression<Func<TEntity, bool>>? expWhere = null);

        bool Any(Expression<Func<TEntity, bool>>? expWhere = null);
        Task<bool> AnyAsync(Expression<Func<TEntity, bool>>? expWhere = null);

        List<TEntity> List(Expression<Func<TEntity, bool>>? expWhere = null, bool noTracking = false);
        Task<List<TEntity>> ListAsync(Expression<Func<TEntity, bool>>? expWhere = null, bool noTracking = false);
    }
}
